/**
 * 
 */
package name.webdizz.gadget.four.envelope.client.presenter;

import name.webdizz.gadget.four.envelope.client.EnvelopePreferences;
import name.webdizz.gadget.four.envelope.client.domain.Envelope;
import name.webdizz.gadget.four.envelope.client.domain.Expense;
import name.webdizz.gadget.four.envelope.client.domain.ExpenseItem;
import name.webdizz.gadget.four.envelope.client.domain.Goal;
import name.webdizz.gadget.four.envelope.client.event.CreditExpenseEventHandler;
import name.webdizz.gadget.four.envelope.client.event.CreditGoalEventHandler;
import name.webdizz.gadget.four.envelope.client.event.Events;
import name.webdizz.gadget.four.envelope.client.event.SaveExpenseEventHandler;
import name.webdizz.gadget.four.envelope.client.request.HeaderAttributes;
import name.webdizz.gadget.four.envelope.client.request.RequestCallback;
import name.webdizz.gadget.four.envelope.client.request.RequestInvoker;
import name.webdizz.gadget.four.envelope.client.request.calback.EnvelopeRequestCalback;
import name.webdizz.gadget.four.envelope.client.util.EnvelopeProvider;
import name.webdizz.gadget.four.envelope.client.util.XmlEnvelopeParser;
import name.webdizz.gadget.four.envelope.client.util.XmlUserParser;
import name.webdizz.gadget.four.envelope.client.view.IEnvelopeView;

import com.google.gwt.xml.client.XMLParser;
import com.mvp4g.client.presenter.Presenter;

/**
 * @author Izzet_Mustafayev
 * 
 */
public class EnvelopePresenter extends Presenter<IEnvelopeView> {

	/**
	 * The reference to {@link EnvelopePreferences}.
	 */
	private EnvelopePreferences envelopePreferences;

	/**
	 * The {@link RequestInvoker} instance.
	 */
	private RequestInvoker requestInvoker;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mvp4g.client.presenter.Presenter#bind()
	 */
	@Override
	public void bind() {
		super.bind();
		view.setSaveExpenseHandler(new SaveExpenseEventHandler() {
			public void onSave(final Expense expense) {
				eventBus.dispatch(Events.SAVE_EXPENSE);
				saveExpense(expense);
			}
		});
		view.setCreditGoalEventHandler(new CreditGoalEventHandler() {
			public void onSave(final Goal goal) {
				eventBus.dispatch(Events.CREDIT_GOAL);
				credit(goal);
			}
		});
		view.setCreditExpenseEventHandler(new CreditExpenseEventHandler() {
			public void onSave(final ExpenseItem expense) {
				eventBus.dispatch(Events.CREDIT_EXPENSE);
				credit(expense);
			}
		});
	}

	public void loadUser() {
		requestInvoker.loadUser(new RequestCallback() {
			public void onResponseReceived(final String response) {
				if (null != response) {
					XmlUserParser.fillUser(EnvelopeProvider.instance()
							.getEnvelope().getUser(), response);
					eventBus.dispatch(Events.SHOW_ENVELOPE);
				}
			}
		});

	}

	private void credit(final Goal goal) {
		requestInvoker.creditGoal(goal, new RequestCallback() {
			public void onResponseReceived(final String response) {
				if (null != response) {
					eventBus.dispatch(Events.GOAL_CREDITED);
					// track expense saving
					requestInvoker.trackUsage("CreditGoal", envelopePreferences
							.username().getValue());
				}
			}
		});
	}

	private void credit(final ExpenseItem expense) {
		requestInvoker.creditExpense(expense, new RequestCallback() {
			public void onResponseReceived(final String response) {
				if (null != response) {
					eventBus.dispatch(Events.EXPENSE_CREDITED);
					// track expense saving
					requestInvoker.trackUsage("CreditExpense",
							envelopePreferences.username().getValue());
				}
			}
		});
	}

	/**
	 * Perform update of given {@link Expense}.
	 * 
	 * @param expense
	 *            the {@link Expense} to update
	 */
	private void saveExpense(final Expense expense) {
		expense.setCurrency(EnvelopeProvider.instance().getEnvelope().getUser()
				.getCurrency());
		requestInvoker.saveExpense(expense, new RequestCallback() {
			public void onResponseReceived(final String response) {
				if (null != response) {
					Expense updatedExpense = XmlEnvelopeParser
							.createExpense(XMLParser.parse(response)
									.getFirstChild());
					updatedExpense.setPersonId(expense.getPersonId());
					eventBus.dispatch(Events.EXPENSE_SAVED, updatedExpense);
					// track expense saving
					requestInvoker.trackUsage("SaveExpense",
							envelopePreferences.username().getValue());
				}
			}
		});
	}

	/**
	 * Load envelope data.
	 */
	public void loadEnvelope() {
		RequestCallback envelopeCallback = new EnvelopeRequestCalback(eventBus);
		requestInvoker.loadEnvelope(envelopeCallback);
	}

	/**
	 * Show envelope data.
	 */
	public void showEnvelope(final Envelope envelope) {
		if (null != envelope) {
			view.showEnvelope(envelope);
			eventBus.dispatch(Events.UPDATE_ENVELOPE_SIZE, view
					.getEnvelopeSize());
			// track envelope loading
			requestInvoker.trackUsage("Envelope", envelopePreferences
					.username().getValue());
		}
	}

	/**
	 * Update view according to changes.
	 * 
	 * @param expense
	 *            the updayed {@link Expense}
	 */
	public void onExpenseSaved(final Expense expense) {
		view.replicateAfterExpenseUpdated(expense);
		eventBus.dispatch(Events.UPDATE_ENVELOPE_SIZE, view.getEnvelopeSize());
	}

	private HeaderAttributes getHeaderAttributes() {
		return new HeaderAttributes(envelopePreferences.apiKey().getValue(),
				envelopePreferences.password().getValue());
	}

	/**
	 * @param envelopePreferences
	 *            the envelopePreferences to set
	 */
	public void setEnvelopePreferences(
			final EnvelopePreferences envelopePreferences) {
		this.envelopePreferences = envelopePreferences;
		requestInvoker = new RequestInvoker(getHeaderAttributes());
	}

}
